package JavaNIO;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
public class NioServer {
    public static void main(String[] args) {
        try {
            // 1. 创建 ServerSocketChannel 用于监听客户端连接
            ServerSocketChannel serverChannel = ServerSocketChannel.open();
            serverChannel.bind(new InetSocketAddress(8080));
            serverChannel.configureBlocking(false); // 设置为非阻塞模式

            // 2. 创建 Selector 并注册 ServerSocketChannel，监听 ACCEPT 事件
            Selector selector = Selector.open();
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);

            System.out.println("NIO Server started on port 8080...");

            while (true) {
                // 3. 检查是否有事件发生，阻塞等待
                if (selector.select() == 0) {
                    continue; // 如果没有事件就绪，继续循环
                }

                // 4. 获取就绪的事件集合
                Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
                while (keyIterator.hasNext()) {
                    SelectionKey key = keyIterator.next();
                    keyIterator.remove(); // 移除当前处理的 key，避免重复处理

                    try {
                        // 5. 处理不同的事件
                        if (key.isAcceptable()) { // 客户端连接事件
                            handleAccept(key, selector);
                        } else if (key.isReadable()) { // 读取客户端数据事件
                            handleRead(key);
                        }
                    } catch (IOException e) {
                        System.err.println("Error handling client connection: " + e.getMessage());
                        key.cancel(); // 取消出错的键
                        if (key.channel() != null) {
                            key.channel().close();
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 处理 ACCEPT 事件
    private static void handleAccept(SelectionKey key, Selector selector) throws IOException {
        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
        SocketChannel clientChannel = serverChannel.accept(); // 接受客户端连接
        clientChannel.configureBlocking(false); // 设置为非阻塞模式
        clientChannel.register(selector, SelectionKey.OP_READ); // 注册 READ 事件
        System.out.println("Client connected: " + clientChannel.getRemoteAddress());
    }

    // 处理 READ 事件
    private static void handleRead(SelectionKey key) throws IOException {
        SocketChannel clientChannel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int bytesRead;

        try {
            bytesRead = clientChannel.read(buffer); // 从通道中读取数据
        } catch (SocketException e) {
            System.err.println("Connection reset by client: " + clientChannel.getRemoteAddress());
            clientChannel.close();
            key.cancel();
            return;
        }

        if (bytesRead > 0) {
            buffer.flip(); // 切换到读取模式
            String message = new String(buffer.array(), 0, buffer.limit());
            System.out.println("Received from client: " + message);

            // 回写数据到客户端
            buffer.clear();
            buffer.put(("Echo: " + message).getBytes());
            buffer.flip();
            clientChannel.write(buffer);
        } else if (bytesRead == -1) { // 客户端断开连接
            System.out.println("Client disconnected: " + clientChannel.getRemoteAddress());
            clientChannel.close();
            key.cancel(); // 取消注册的事件
        }
    }
}
